package cn.edu.nju.software.zp13.client.assignment3.xmlGenerator;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;

public class XmlGenerator {
	private Document dom;
	private XmlContentStrategy xmlContent;

	/**
	 * if no parameters in constructor,xmlGenerator will create a new Document
	 */
	public XmlGenerator() {
		try {
			dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		}
	}

	/**
	 * create a dom tree parsed from xmlFileSource
	 * 
	 * @param filePath
	 *            xmlFileSource
	 */
	public XmlGenerator(String filePath) {
		try {
			dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new FileInputStream(filePath));
		} catch (ParserConfigurationException | SAXException | IOException e) {
			e.printStackTrace();
		}
	}

	public void setDom(Document dom){
		this.dom=dom;
	}
	
	
	public Document getNewDom() {
		xmlContent.processDom(dom);
		return dom;
	}

	/**
	 * create a xml File,invoke strategy's processDom method to update dom
	 * 
	 * @param targetFilePath
	 */
	public void createXml(String targetFilePath) {
		xmlContent.processDom(dom);
		writeXml(targetFilePath);
	}

	public XmlContentStrategy getXmlContent() {
		return xmlContent;
	}

	/**
	 * set concrete XmlContentstrategy to generate concrete DOM tree.
	 * 
	 * @param xmlContent
	 *            concrete XmlContentstrategy.
	 */
	public void setXmlContent(XmlContentStrategy xmlContent) {
		this.xmlContent = xmlContent;
	}

	private void writeXml(String fileName) {
		TransformerFactory tf = TransformerFactory.newInstance();
		tf.setAttribute("indent-number", 4);
		try {
			Transformer transformer = tf.newTransformer();
			DOMSource source = new DOMSource(dom);
			transformer.setOutputProperty(OutputKeys.ENCODING, "utf-8");
			transformer.setOutputProperty(OutputKeys.INDENT, "yes");
			PrintWriter pw = new PrintWriter(new FileOutputStream(fileName));
			StreamResult result = new StreamResult(pw);
			transformer.transform(source, result);
			System.out.println("File " + fileName + " created successfully!");
		} catch (TransformerConfigurationException e) {
			System.out.println(e.getMessage());
		} catch (IllegalArgumentException e) {
			System.out.println(e.getMessage());
		} catch (FileNotFoundException e) {
			System.out.println(e.getMessage());
		} catch (TransformerException e) {
			System.out.println(e.getMessage());
		}
	}

}
